package experiment;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Random;


import metrics.Evaluate;
import metrics.Rouge;
import summarizer.PinakiSummarizer;
import summarizer.newversion.ClusterSummarizer;
import summarizer.newversion.GreedySummarizerItOptNewFilterSimple;
import summarizer.newversion.RandomSummarizer;
import summarizer.newversion.Summarizer;
import thesis.DataObject;
import thesis.FSModule;
import thesis.InfoUnit;
import thesis.Summary;

public class RobustExp {
	public static double[][] ground;
	static boolean first = true;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HashMap<Long, DataObject> memoryTweets = new HashMap<Long, DataObject>();
		List<Dimension> dimensions = new ArrayList<Dimension>();
		ArrayList<Double> weights = new ArrayList<Double>();
		double alpha = 0.3, beta = 0, gamma = 1;
		// get data from DB
		FSModule.getDataFromDB(memoryTweets, dimensions, weights);
		alpha = FSModule.getQualityWeigth();
		beta = FSModule.getDiversityWeigth();
		gamma = FSModule.getCoverageWeigth();
		// get data from File
		// try {
		// String fileName = "res/toyExample.txt";
		// DataFromFile.createToyExample3(fileName);
		// DataFromFile.getDataFromFile(fileName, memoryTweets, dimensions,
		// weights);
		// } catch (IOException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
		testRobust(memoryTweets, dimensions, weights, alpha, beta, gamma);

	}

	public static void testRobust(HashMap<Long, DataObject> memoryTweets,
			List<Dimension> dimensions,
			ArrayList<Double> weights, double alpha, double beta, double gamma) {
		int[] dim = new int[dimensions.size()];
		boolean[] norm = {true, true, true, true, true};
		for (int i = 0; i < dimensions.size(); i++) {
			dim[i] = i;
		}
		ArrayList<Double> lamdas = new ArrayList<Double>();
		ArrayList<Double[]> scores = new ArrayList<Double[]>();

		ArrayList<Dimension> rndDims = new ArrayList<Dimension>();
		ArrayList<Dimension> oriDims = new ArrayList<Dimension>();
		for (int i = 0; i < dim.length; i++) {
			Dimension rndDim = new Dimension();
			oriDims.add(dimensions.get(dim[i]));
			for (Long id : memoryTweets.keySet()) {
				for (String key : oriDims.get(i).value2obj.keySet()) {
					HashMap<Long, Double> map = rndDim.value2obj.get(key);
					if (map == null) {
						map = new HashMap<Long, Double>();
						rndDim.value2obj.put(key, map);
					}
					map.put(id, new Random().nextDouble());
				}
			}
			rndDims.add(rndDim);
		}
		for (double lamda = 0.0; lamda <= 1.1; lamda += 0.2) {
			HashMap<Long, DataObject> copyObjects = (HashMap<Long, DataObject>) memoryTweets
					.clone();
			for (DataObject obj : copyObjects.values()) {
				obj.reset();
			}
			for (int i = 0; i < dim.length; i++) {
				Dimension copyDim = new Dimension();
				for (Long id : copyObjects.keySet()) {
					double totalOrig = 0;
					for (String key : oriDims.get(i).value2obj.keySet()) {
						Double p = oriDims.get(i).value2obj.get(key).get(id);
						totalOrig += p == null ? 0 : p;
					}
					double totalMix = 0;
					for (String key : oriDims.get(i).value2obj.keySet()) {
						HashMap<Long, Double> map = copyDim.value2obj.get(key);
						if (map == null) {
							map = new HashMap<Long, Double>();
							copyDim.value2obj.put(key, map);
						}
						Double prob = oriDims.get(i).value2obj.get(key).get(id);
						prob = prob == null ? 0 : prob;
						Double rndProb = rndDims.get(i).value2obj.get(key).get(id);
						rndProb = rndProb == null ? 0 : rndProb;
						double mixProb = (1 - lamda) * prob + lamda * rndProb;
						if (mixProb > 0) {
							map.put(id, mixProb);
						}
						totalMix += mixProb;
					}
					for (String key : copyDim.value2obj.keySet()) {
						HashMap<Long, Double> map = copyDim.value2obj.get(key);
						Double prob = map.get(id);
						if (prob != null) {
							map.put(id, norm[i] ? prob / totalMix * totalOrig
									: prob);
						}
					}
				}
				dimensions.set(dim[i], copyDim);
			}
			Double[] score = getRougeScore(copyObjects, dimensions, weights,
					alpha, beta, gamma);
			lamdas.add(lamda);
			scores.add(score);
		}
		for (int i = 0; i < lamdas.size(); i++) {
			System.out.printf("%.4f\t", lamdas.get(i));
			for (int j = 0; j < scores.get(i).length; j++) {
				System.out.printf("%.4f\t", scores.get(i)[j]);
			}
			System.out.println();
		}
	}

	public static Double[] getRougeScore(
			HashMap<Long, DataObject> memoryTweets,
			List<Dimension> dimensions,
			ArrayList<Double> weights, double alpha, double beta, double gamma) {
		// --------------------convert attributes to info units---------------
		int K = 20;
		ArrayList<InfoUnit> infoUnits = new ArrayList<InfoUnit>();
		double[][] probs = Preprocess.prepareForSummarization(memoryTweets,
				dimensions, weights, infoUnits);
		// add summarizers
		ArrayList<Summarizer> summarizers = new ArrayList<Summarizer>();
		summarizers.add(new GreedySummarizerItOptNewFilterSimple(probs,
				infoUnits, alpha, beta, gamma));
		// summarizers.add(new ClusterSummarizer());
		summarizers.add(new PinakiSummarizer(probs, alpha, beta, gamma));
		summarizers.add(new RandomSummarizer());
		ArrayList<Summary>[] summaries = new ArrayList[summarizers.size()];
		for (int i = 0; i < summarizers.size(); i++) {
			int repeat = summarizers.get(i).rndAlgo ? 5 : 1;
			summaries[i] = new ArrayList<Summary>();
			for (int j = 0; j < repeat; j++) {
				summaries[i].add(summarizers.get(i).computeSummary(K, 1,
						(HashMap<Long, DataObject>) memoryTweets.clone(),
						dimensions.size()));
			}
		}
		if (first) {
			Evaluate.toBinary(memoryTweets.values(), infoUnits, probs);
			ground = probs;
			first = false;
		}
		Double[] scores = new Double[summaries.length];
		for (int i = 0; i < scores.length; i++) {
			double score = 0;
			for (int j = 0; j < summaries[i].size(); j++) {
				score += Rouge.getScore(summaries[i].get(j),
						memoryTweets.values(), infoUnits, ground);
			}
			scores[i] = score / summaries[i].size();
		}
		return scores;

	}
}
